%% TDMA主函数 - 时分多址仿真
% 本程序模拟了时分多址接入技术，这是第二代移动通信(2G)使用的多址接入技术
% 在TDMA中，同一频率信道上的时间被分为多个时隙，每个用户被分配特定的时隙

clear all;
close all;
clc;

%% 参数设置
num_users = 8;         % 用户数量
num_frames = 10;       % 传输帧数
slots_per_frame = 8;   % 每帧时隙数
bits_per_slot = 148;   % 每个时隙的比特数（GSM标准）
guard_bits = 8;        % 保护间隔比特数
M = 2;                 % 调制阶数 (GMSK类似于2-PSK)
snr_dB = 15;           % 信噪比(dB)

% 是否模拟不完整的一帧（部分用户的时隙为空）
incomplete_frame = true;
active_users = [1, 2, 4, 5, 7];  % 仅这些用户活跃（只有num_users为较大值时设置）

% 计算总比特数
total_bits_per_frame = slots_per_frame * (bits_per_slot + guard_bits);
total_bits = num_frames * total_bits_per_frame;

fprintf('开始TDMA仿真，共%d个用户，%d帧，每帧%d个时隙\n', num_users, num_frames, slots_per_frame);

%% 生成用户数据并创建TDMA帧
% 初始化用户数据和TDMA帧
user_data = cell(1, num_users);
tdma_frames = zeros(num_frames, total_bits_per_frame);

fprintf('创建用户数据...\n');
% 为每个用户生成随机比特
for user = 1:num_users
    bits_per_user = num_frames * bits_per_slot;
    user_data{user} = randi([0 1], 1, bits_per_user);
end

% 创建TDMA帧
fprintf('构建TDMA帧...\n');
for frame = 1:num_frames
    for slot = 1:slots_per_frame
        % 判断该时隙对应哪个用户
        user = mod(slot-1, num_users) + 1;
        
        % 检查用户是否处于活跃状态
        is_active = ~incomplete_frame || ismember(user, active_users);
        
        if is_active
            % 计算当前用户在该帧的数据索引
            user_bits_idx = (frame-1)*bits_per_slot + 1;
            
            % 用户数据位置
            slot_start = (slot-1)*(bits_per_slot + guard_bits) + 1;
            slot_data_range = slot_start:(slot_start + bits_per_slot - 1);
            
            % 将用户数据放入对应的时隙
            tdma_frames(frame, slot_data_range) = user_data{user}(user_bits_idx:(user_bits_idx + bits_per_slot - 1));
            
            % 添加保护间隔
            guard_start = slot_start + bits_per_slot;
            guard_end = guard_start + guard_bits - 1;
            tdma_frames(frame, guard_start:guard_end) = zeros(1, guard_bits);
        end
    end
end

%% 调制TDMA帧
fprintf('TDMA帧调制...\n');
modulated_frames = cell(1, num_frames);
for frame = 1:num_frames
    % 调制当前帧
    modulated_frames{frame} = tdma_modulate(tdma_frames(frame, :), M);
end

%% 通过AWGN信道传输
fprintf('通过AWGN信道传输...\n');
received_frames = cell(1, num_frames);
for frame = 1:num_frames
    received_frames{frame} = add_noise_to_signal(modulated_frames{frame}, snr_dB);
end

%% 接收和解调
fprintf('接收并解调TDMA帧...\n');
received_bits = cell(1, num_users);
for user = 1:num_users
    received_bits{user} = zeros(1, num_frames * bits_per_slot);
end

% 解调每一帧
demodulated_frames = cell(1, num_frames);
for frame = 1:num_frames
    % 解调整帧
    demodulated_frame = tdma_demodulate(received_frames{frame}, M);
    demodulated_frames{frame} = demodulated_frame;
    
    % 提取每个用户的数据
    for slot = 1:slots_per_frame
        user = mod(slot-1, num_users) + 1;
        
        % 只处理活跃用户
        if ~incomplete_frame || ismember(user, active_users)
            % 计算时隙在帧中的位置
            slot_start = (slot-1)*(bits_per_slot + guard_bits) + 1;
            slot_data_range = slot_start:(slot_start + bits_per_slot - 1);
            
            % 计算用户数据存储位置
            user_bits_idx = (frame-1)*bits_per_slot + 1;
            
            % 提取用户数据
            received_bits{user}(user_bits_idx:(user_bits_idx + bits_per_slot - 1)) = demodulated_frame(slot_data_range);
        end
    end
end

%% 计算误码率
fprintf('计算误码率...\n');
ber = zeros(1, num_users);
active_user_count = 0;

for user = 1:num_users
    % 只计算活跃用户的误码率
    if ~incomplete_frame || ismember(user, active_users)
        active_user_count = active_user_count + 1;
        bit_errors = sum(received_bits{user} ~= user_data{user});
        ber(user) = bit_errors / length(user_data{user});
        fprintf('用户 %d 的误码率: %.6f\n', user, ber(user));
    end
end

% 计算平均误码率
avg_ber = sum(ber) / active_user_count;
fprintf('所有用户的平均误码率: %.6f\n', avg_ber);

%% 可视化TDMA帧结构
fprintf('绘制TDMA帧结构...\n');
visualize_tdma_frame(tdma_frames, num_users, active_users, incomplete_frame);

%% 绘制时域信号
fprintf('绘制TDMA时域信号...\n');
plot_tdma_signals(modulated_frames, num_users, slots_per_frame, bits_per_slot, guard_bits);

fprintf('TDMA仿真完成!\n'); 